package turtle.system.invest.evaluate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.osite.util.IntArray;
import org.osite.util.Preconditions;
import org.osite.util.ToolKit;
import org.osite.xml.XmlConstructor;
import org.osite.xml.XmlParam;

import turtle.system.invest.BarType;
import turtle.system.invest.Environment;
import turtle.system.invest.IndexSeries;
import turtle.system.invest.Util;
import turtle.system.invest.rule.InvestRunnable;

public class IndexBuilder implements InvestRunnable {

    private static final int COLUMN_OFFSET = 1;
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");

    private final String name;
    private final String resource;
    private final String encode;

    @XmlConstructor
    public IndexBuilder(
            @XmlParam("name") String name,
            @XmlParam("resource") String resource,
            @XmlParam(value = "encode", preset = "utf-8") String encode) {
        this.name = Preconditions.checkNotNull(name);
        this.resource = Preconditions.checkNotNull(resource);
        this.encode = Preconditions.checkNotNull(encode);
    }

    @Override
    public void run(Environment environment) {
        InputStream inputStream = environment.getResource(resource);
        if (inputStream == null) {
            throw new RuntimeException("cannot find resource: " + resource);
        }
        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(inputStream, encode));
            
            ArrayList<Date> dateList = ToolKit.newArrayList();
            
            Util.skipLines(reader, 3);
            BarType types[] = BarType.values();
            IntArray array[] = new IntArray[types.length];
            for (int i = 0, n = array.length; i < n; ++i) {
                array[i] = new IntArray();
            }
            String line = reader.readLine();
            try {
                while (line != null) {
                    if (!line.trim().isEmpty()) {
                        String token[] = line.split("[\t ]+", -1);
                        dateList.add(DATE_FORMAT.parse(token[0]));
                        for (int i = 0, n = array.length; i < n; ++i) {
                            array[i].put((int) Math.round(Double.parseDouble(
                                    token[COLUMN_OFFSET + i]) * 100.0));
                        }
                    }
                    line = reader.readLine();
                }
            } catch (Exception e) {
                throw new RuntimeException("invalid line: " + line, e);
            }
            environment.set(name + ".date", dateList.toArray(new Date[0]));
            for (int i = 0, n = array.length; i < n; ++i) {
                environment.set(getKey(name, types[i]),
                        new IndexSeries(array[i].toArray()));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            Util.closeSiliently(inputStream);
        }
    }

    public static String getKey(String name, BarType type) {
        return name + '.' + type.name().toLowerCase();
    }
}
